﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Day2
{
    class Program
    {
        static void Main(string[] args)
        {
            ListWithParallel();
            ConcurrentBagWithParallel();
            ConcurrentBagWithParallel2();
            TestPLinq();
            OrderByTest();
        }

        #region demo1
        /// <summary>
        /// List<T>集合
        /// List<T>是非线程安全集合，意思就是说所有的线程都可以修改他的值
        /// </summary>
        private static void ListWithParallel()
        {
            List<int> list = new List<int>();
            Parallel.For(0, 10000, (item) =>
            {
                list.Add(item);
            });
            Console.WriteLine("List`s count is {0}", list.Count());
        }
        #endregion

        #region demo2
        /// <summary>
        /// 线程安全
        /// </summary>
        private static void ConcurrentBagWithParallel()
        {
            ConcurrentBag<int> list = new ConcurrentBag<int>();
            Parallel.For(0, 10000, (item) =>
            {
                list.Add(item);
            });
            Console.WriteLine("ConcurrentBag`s count is {0}", list.Count());
        }
        #endregion

        #region demo3
        /// <summary>
        /// 查看ConcurrentBag中的数据是怎样存放的
        /// </summary>
        private static void ConcurrentBagWithParallel2()
        {
            ConcurrentBag<int> list = new ConcurrentBag<int>();
            Parallel.For(0, 10000, (item) =>
            {
                list.Add(item);
            });
            Console.WriteLine("ConcurrentBag`s count is {0}", list.Count());
            int n = 0;
            foreach (int l in list)
            {
                if (n > 10)
                {
                    break;
                }
                n++;
                Console.WriteLine($"Item[{n}] = {l}");
            }
            Console.WriteLine($"ConcurrentBag`s max item is {list.Max()}");
        }
        #endregion

        #region demo4 AsParallel Parallel Linq的性能和用法
        /// <summary>
        /// 使用AsParallel实现用户查询的并行化处理
        /// </summary>
        private static void TestPLinq()
        {
            Stopwatch stopwatch = new Stopwatch();
            List<Custom> customs = new List<Custom>();
            for (int i = 0; i < 200000; i++)
            {
                customs.Add(new Custom() { Name = "Jack", Age = 21, Address = "NewYork" });
                customs.Add(new Custom() { Name = "Jime", Age = 26, Address = "China" });
                customs.Add(new Custom() { Name = "Tina", Age = 29, Address = "ShangHai" });
                customs.Add(new Custom() { Name = "Luo", Age = 30, Address = "Beijing" });
                customs.Add(new Custom() { Name = "Wang", Age = 60, Address = "GuangDong" });
                customs.Add(new Custom() { Name = "Feng", Age = 25, Address = "YunNan" });
            }
            stopwatch.Start();
            var result = customs.Where<Custom>((c) => c.Age > 26).ToList();
            stopwatch.Stop();
            Console.WriteLine($"Linq time is {stopwatch.ElapsedMilliseconds}");
            stopwatch.Restart();
            var result2 = customs.AsParallel().Where<Custom>((c) => c.Age > 26).ToList();
            stopwatch.Stop();
            Console.WriteLine($"Parallel Linq time is {stopwatch.ElapsedMilliseconds}");
        }
        #endregion

        #region demo5 GroupBy操作ToLookup方法
        private static void OrderByTest()
        {
            Stopwatch stopwatch = new Stopwatch();
            List<Custom> customs = new List<Custom>();
            for (int i = 0; i < 200000; i++)
            {
                customs.Add(new Custom() { Name = "Jack", Age = 21, Address = "NewYork" });
                customs.Add(new Custom() { Name = "Jime", Age = 26, Address = "China" });
                customs.Add(new Custom() { Name = "Tina", Age = 29, Address = "ShangHai" });
                customs.Add(new Custom() { Name = "Luo", Age = 30, Address = "Beijing" });
                customs.Add(new Custom() { Name = "Wang", Age = 60, Address = "GuangDong" });
                customs.Add(new Custom() { Name = "Feng", Age = 25, Address = "YunNan" });
            }
            stopwatch.Start();
            var groupByAge = customs.GroupBy(item => item.Age).ToList();
            foreach(var item in groupByAge)
            {
                Console.WriteLine($"Age={item.Key}, count={item.Count()}");
            }
            stopwatch.Stop();
            Console.WriteLine($"Linq groupBy time is {stopwatch.ElapsedMilliseconds}");
            stopwatch.Restart();
            var Lookuplist = customs.ToLookup(i => i.Age).ToList();
            foreach(var item in Lookuplist)
            {
                Console.WriteLine($"LookUP:Age={item.Key}, count={item.Count()}");
            }
            stopwatch.Stop();
            Console.WriteLine($"Lookup group by time is {stopwatch.ElapsedMilliseconds}");
        }
        #endregion
    }

    class Custom
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }
}
